home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Just Call Me Internet
/
Just Call Me Internet.iso
/
com
/
othernet
/
fidonet
/
doorm003
/
doormail.c
next >
Wrap
C/C++ Source or Header
|
1994-04-07
|
21KB
|
804 lines
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <fido.h>
#include <ext.h>
#include <tos.h>
#include <ctype.h>
#include <time.h>
#define MAX_STR 256
#define TRUE 1
#define FALSE 0
#define EOS '\0'
#define MIN(x,y) ((x)<(y)) ? (x) : (y)
#define MAX(x,y) ((x)>(y)) ? (x) : (y)
#define MINSTACK 100
#define MAXSTACK 10000
#define MAXALLOWED 100
#define X_FIXNAME "Doormail"
#define X_TEARLINE "\n=== Doormail V0.03\n"
#define X_PID "\001PID: Doormail 0.03\n"
#define C_EXEC (1 << 0)
#define C_DEL (1 << 1)
#define C_REQUEST (1 << 2)
#define C_NOTIFY (1 << 3)
extern int match(char *pattern,char *string);
extern int matchfile(char *pattern,char *filename);
void convert(char *buffer, int *length);
char *mergeaddr(char *addr,int zone,int net,int node,int point,char *domain);
void scanaddr(char *addr,int *zone,int *net,int *node,int *point,char *domain);
void trim(char **dest);
void parse(char *buffer,int size);
void parse_it(char *line);
void writenotify(void);
void delete_unused_flags(MSG_HEADER *header);
void input(char *string, int max, FILE *ftype);
int do_exec(char *fname);
char *trimstr(char *str);
void getpfad(char *fname, char *xpfad);
void log_it(char *text);
int xFsfirst(const char *filename,int attr);
int xFsnext(void);
int delete(char *fname);
int teste_ob_in_okfile(char *filename);
int untersuche_ordner(char *fname,char *request,int add);
char *addr2file36(unsigned int net,unsigned int node,unsigned int point);
void add_slash(char *path);
typedef struct { char name[40],
passwd[40];
int zone,net,node,point,
wildcards,
nopasswd,
cmd;
} ALLOWED;
typedef struct { char line[128];
} ERRSTACK;
char netmail[PATH_MAX]="",
logfile[PATH_MAX]="",
okfile[PATH_MAX]="",
outbound[PATH_MAX]="",
buffer[65535U],*fbuffer;
int myzone,mynet,mynode,mypoint,
allowed_cnt=0,
err_cnt,
max_errline,
wildcard=FALSE,
aktive_user;
ERRSTACK *errstack;
ALLOWED allowed[MAXALLOWED];
MSG_HEADER mh;
FILE *fhdr,*fmsg;
DTA dta_buffer;
int main(void)
{ char temp[MAX_STR],*pointer;
long size,msgs,i,t;
int noerror,j;
t = (((long)Malloc(-1L))-65536L)/sizeof(*errstack);
if (t>MAXSTACK) t=MAXSTACK;
if (t<MINSTACK) t=MINSTACK;
max_errline = (int) t;
errstack = (ERRSTACK *) calloc(max_errline+2,sizeof(*errstack));
fbuffer=(char *)malloc(sizeof(MSG_HEADER)*40);
if (fbuffer==NULL)
{ free(errstack);
exit(1);
}
fhdr = fopen("DOORMAIL.CFG","rb");
do
{ input(temp,MAX_STR,fhdr);
pointer=temp; trim(&pointer); strcpy(temp,pointer);
if (strnicmp(temp,"WILDCARD",8)==0)
{ wildcard=TRUE;
continue;
}
if (strnicmp(temp,"NETMAIL ",8)==0)
{ pointer+=8; trim(&pointer);
strcpy(netmail,pointer);
continue;
}
if (strnicmp(temp,"LOGFILE ",8)==0)
{ pointer+=8; trim(&pointer);
strcpy(logfile,pointer);
continue;
}
if (strnicmp(temp,"OKFILE ",7)==0)
{ pointer+=7; trim(&pointer);
strcpy(okfile,pointer);
continue;
}
if (strnicmp(temp,"OUTBOUND ",9)==0)
{ pointer+=9; trim(&pointer);
strcpy(outbound,pointer);
add_slash(outbound);
continue;
}
if (strnicmp(temp,"ADDRESS ",8)==0)
{ pointer+=8; trim(&pointer);
scanaddr(pointer,&myzone,&mynet,&mynode,&mypoint,temp);
continue;
}
if (strnicmp(temp,"PASSWORD ",9)==0)
{ pointer+=9; trim(&pointer); strcpy(temp,pointer);
pointer=strtok(temp," ");
allowed_cnt++;
allowed[allowed_cnt].wildcards=FALSE;
allowed[allowed_cnt].nopasswd=TRUE;
allowed[allowed_cnt].cmd=-1; /* Alle erlaubt */
while (*pointer=='#' || *pointer=='!')
{ if (*pointer=='!')
{ strcpy(allowed[allowed_cnt].passwd,pointer+1);
allowed[allowed_cnt].nopasswd=FALSE;
}
if (*pointer=='#')
{ allowed[allowed_cnt].cmd=0;
if (strchr(pointer+1,'*')!=NULL)
allowed[allowed_cnt].wildcards=TRUE;
if (strchr(pointer+1,'e')!=NULL ||
strchr(pointer+1,'E')!=NULL )
allowed[allowed_cnt].cmd |= C_EXEC;
if (strchr(pointer+1,'n')!=NULL ||
strchr(pointer+1,'N')!=NULL )
allowed[allowed_cnt].cmd |= C_NOTIFY;
if (strchr(pointer+1,'r')!=NULL ||
strchr(pointer+1,'R')!=NULL )
allowed[allowed_cnt].cmd |= C_REQUEST;
if (strchr(pointer+1,'d')!=NULL ||
strchr(pointer+1,'D')!=NULL )
allowed[allowed_cnt].cmd |= C_DEL;
}
pointer=strtok(NULL," ");
}
scanaddr(pointer, &allowed[allowed_cnt].zone,
&allowed[allowed_cnt].net,
&allowed[allowed_cnt].node,
&allowed[allowed_cnt].point,temp);
pointer=strtok(NULL,"");
trim(&pointer);
strcpy(allowed[allowed_cnt].name,pointer);
continue;
}
}
while (feof(fhdr)==0);
fclose(fhdr);
sprintf(temp,"%s.HDR",netmail);
fhdr = fopen( temp,"r+b" );
setvbuf(fhdr,fbuffer,_IOFBF,sizeof(MSG_HEADER)*40);
size = filelength( fhdr->Handle);
msgs = size / sizeof( MSG_HEADER );
for (i=1; i<=msgs; i++)
{ noerror=0;
if (fread( &mh,sizeof(MSG_HEADER),1,fhdr)==1)
noerror |= 1;
if (!mh.wProcessed.Doormail && !(mh.wFlags & MF_DELETED))
{
if (stricmp(mh.szTo,X_FIXNAME)==0)
noerror |= 2;
if (mh.wToZone ==myzone && mh.wToNet ==mynet &&
mh.wToNode ==mynode && mh.wToPoint==mypoint)
noerror |= 4;
aktive_user=0;
for (j=1; j<=allowed_cnt; j++)
{ if (stricmp(mh.szFrom,allowed[j].name)==0 &&
(stricmp(mh.szSubject,allowed[j].passwd)==0 || allowed[j].nopasswd==TRUE) &&
mh.wFromZone ==allowed[j].zone &&
mh.wFromNet ==allowed[j].net &&
mh.wFromNode ==allowed[j].node &&
mh.wFromPoint==allowed[j].point)
{ noerror |= 8;
aktive_user=j;
break;
}
}
if ( noerror==15 )
{ sprintf(temp,"Message to Doormail from %s",mh.szFrom);
log_it(temp);
err_cnt=0;
sprintf(temp,"%s.MSG",netmail);
fmsg = fopen( temp,"rb" );
fseek(fmsg,mh.lStart,SEEK_SET);
fread(&buffer,sizeof(char),mh.wSize,fmsg);
fclose(fmsg);
#if !defined( TEST )
fflush(fhdr);
fseek(fhdr,-sizeof(MSG_HEADER),SEEK_CUR);
mh.wProcessed.Doormail = TRUE;
fwrite(&mh,sizeof(MSG_HEADER),1,fhdr);
fflush(fhdr);
#endif
convert(buffer,&mh.wSize);
buffer[mh.wSize] = EOS;
parse(buffer,mh.wSize);
}
else
{ if ( noerror==15-8 )
{ mergeaddr(buffer,mh.wFromZone,mh.wFromNet,mh.wFromNode,mh.wFromPoint,"");
sprintf(temp,"Warning! Mail to Doormail from %s on %s (%s)",mh.szFrom,buffer,mh.szSubject);
log_it(temp);
}
}
}
}
fclose(fhdr);
free(fbuffer);
free(errstack);
return 0;
}
void parse(char *buffer,int size)
{ char *pointer;
pointer=strtok(buffer,"\n\r");
while (pointer!=NULL && (pointer<buffer+size))
{ trim(&pointer);
if (strcmp(pointer,"---")==0)
return;
if (*pointer!=EOS)
parse_it(pointer);
pointer=strtok(NULL,"\n\r");
}
}
void parse_it(char *line)
{ char temp[MAX_STR];
int i;
strcpy(temp,line);
strcpy(errstack[++err_cnt].line,temp);
if (strnicmp(temp,"%NOTIFY",7)==0)
{ if (allowed[aktive_user].cmd & C_NOTIFY)
{ writenotify();
}
else
{ strcpy(errstack[++err_cnt].line,"> NOTIFY disabled!");
log_it("NOTIFY denied");
}
return;
}
if (strnicmp(temp,"%DEL ",5)==0)
{ if (allowed[aktive_user].cmd & C_DEL)
{ if (delete(temp+5)==-32767)
strcpy(errstack[++err_cnt].line,"> Error in DEL! Filename was missing!");
}
else
{ strcpy(errstack[++err_cnt].line,"> DEL disabled!");
log_it("DEL denied");
}
return;
}
if (strnicmp(temp,"%EXEC ",6)==0)
{ if (allowed[aktive_user].cmd & C_EXEC)
{ switch(i=do_exec(temp+6))
{ case -32767 : strcpy(errstack[++err_cnt].line,"> Error in EXEC! Filename was missing!"); break;
case 0 : break;
default : sprintf(errstack[++err_cnt].line,"> EXEC returns %d",i);
}
}
else
{ strcpy(errstack[++err_cnt].line,"> EXEC disabled!");
log_it("EXEC denied");
}
return;
}
if (allowed[aktive_user].cmd & C_REQUEST)
{ i=teste_ob_in_okfile(temp);
log_it(temp);
sprintf(temp," ... %u match%s",i,i==1 ? "" : "es");
strcat(errstack[err_cnt].line,temp);
log_it(temp);
}
else
{ strcpy(errstack[++err_cnt].line,"> REQUEST disabled!");
log_it("REQUEST denied");
}
}
int untersuche_ordner(char *fname,char *request,int add)
{ char source[PATH_MAX],pfad[PATH_MAX],temp[PATH_MAX],*pointer;
int error,i=0;
FILE *fp;
strcpy(source,fname);
getpfad(source,pfad);
/*
** Ist es ein Request MIT Wildcards und ist Request ein
** Pattern von fname?
*/
if (strchr(request,'*')==NULL &&
strchr(request,'?')==NULL)
{ pointer=strrchr(fname,'\\');
if (pointer!=NULL)
pointer++;
else
pointer=fname;
if (matchfile(pointer,request))
{ strcpy(source,pfad);
strcat(source,request);
}
}
error=xFsfirst(source,0);
if (error<0)
{ return 0;
}
while (error>=0)
{ strcpy(source,pfad);
strcat(source,dta_buffer.d_fname);
if (matchfile(request,dta_buffer.d_fname))
{ i++;
if (add)
{ strcpy(temp,outbound);
strcat(temp,addr2file36(allowed[aktive_user].net,
allowed[aktive_user].node,
allowed[aktive_user].point));
strcat(temp,".HFT");
fp=fopen(temp,"a");
fputs(source,fp); fputc('\n',fp);
fclose(fp);
}
}
error=xFsnext();
}
return i;
}
int teste_ob_in_okfile(char *request)
{ FILE *fp;
int i;
char temp[MAX_STR],
t1[MAX_STR],
t2[MAX_STR],
t3[MAX_STR],
filepassword[MAX_STR],
*pointer,
matches=0;
if (wildcard==FALSE && allowed[aktive_user].wildcards==FALSE)
{ pointer=request;
while (*pointer!=EOS && *pointer!='.')
{ if (*pointer=='*' || *pointer=='?')
{ strcpy(errstack[++err_cnt].line,"> Sorry no wildcards in filenames allowed!");
return 0;
}
pointer++;
}
}
*filepassword=EOS;
switch(sscanf(request,"%s %s",&t1,&t2))
{ case 0 : return 0;
case 1 : break;
case 2 : strcpy(request,t1);
strcpy(filepassword,t2);
break;
}
if (*okfile)
{ fp=fopen(okfile,"r");
do
{ input(temp,MAX_STR,fp);
pointer=temp; trim(&pointer); strcpy(temp,pointer);
switch(sscanf(temp,"%s %s %s",&t1,&t2,&t3))
{ case 0 :
case EOF: break;
case 1 : { /* Kein Pawort */
matches += untersuche_ordner(t1,request,TRUE);
} break;
case 2 : { if (*t1=='@')
{ /* MAGIC ohne Pawort*/
if (stricmp(request,t1+1)==0)
{ pointer=strrchr(t2,'\\');
if (pointer!=NULL)
pointer++;
else
pointer=t2;
matches += untersuche_ordner(t2,pointer,TRUE);
}
}
else
{ /* Request mit Pawort */
if (stricmp(filepassword,t2+1)==0)
{ matches += untersuche_ordner(t1,request,TRUE);
}
else
{ if ((i=untersuche_ordner(t1,request,FALSE))!=0)
{ strcpy(errstack[++err_cnt].line,"> Sorry, wrong or missing password!");
log_it(" ... wrong or missing password");
}
matches+=i;
}
}
} break;
case 3 : { /* MAGIC mit Pawort */
if (stricmp(request,t1+1)==0)
{ pointer=strrchr(t3,'\\');
if (pointer!=NULL)
pointer++;
else
pointer=t3;
if (stricmp(filepassword,t2+1)==0)
{ matches += untersuche_ordner(t3,pointer,TRUE);
}
else
{ if ((i=untersuche_ordner(t3,pointer,FALSE))!=0)
{ strcpy(errstack[++err_cnt].line,"> Sorry, wrong or missing password!");
log_it(" ... wrong or missing password");
}
matches+=i;
}
}
} break;
default : log_it("ERROR! ERROR in OKFILE!");
}
}
while (feof(fp)==0);
fclose(fp);
}
else
{ strcpy(errstack[++err_cnt].line,"> Request not possible!");
}
return matches;
}
int delete(char *fname)
{ char source[PATH_MAX],pfad[PATH_MAX],*start;
signed int error;
log_it("Following files deleted:");
start=fname; trim(&start); strcpy(fname,start);
if (*fname==EOS)
{ log_it("None (filename missing)");
return(-32767);
}
strcpy(source,start);
getpfad(source,pfad);
error=xFsfirst(source,0);
if (error<0)
{ sprintf(source,"None (%s not found)",source);
log_it(source);
strcpy(errstack[++err_cnt].line,"> File not found");
}
while (error>=0)
{ strcpy(source,pfad);
strcat(source,dta_buffer.d_fname);
if (Fdelete(source)!=0)
{ sprintf(source,"Unable to kill %s",dta_buffer.d_fname);
log_it(source);
sprintf(errstack[++err_cnt].line,">%s unable to delete",dta_buffer.d_fname);
}
else
{ log_it(dta_buffer.d_fname);
sprintf(errstack[++err_cnt].line,">%s",dta_buffer.d_fname);
}
error=xFsnext();
}
return 0;
}
int do_exec(char *fname)
{ char source[PATH_MAX],cmd[PATH_MAX],temp[MAX_STR],*start;
int drive=0;
start=fname; trim(&start); strcpy(fname,start);
if (*fname==EOS)
return(-32767);
while(!isspace(*start) && *start!=EOS) start++;
if (*start==EOS) /* Keine Kommandozeile */
drive=1;
*start=EOS;
strcpy(source,fname);
if (drive==0)
{ start++;
strcpy(temp,start);
}
else
{ *temp=EOS;
}
trimstr(temp); /* Kommandozeile */
cmd[0]=strlen(temp);
cmd[1]=EOS;
strcpy(&cmd[1],temp);
if (*(source+1)==':')
{ drive=toupper(*(source))-'A';
Dsetdrv(drive);
}
getpfad(source,temp);
Dsetpath(temp);
sprintf(temp,"Executing %s %s",source,cmd+1);
log_it(temp);
return((int)Pexec(0,source,cmd,NULL));
}
void writenotify(void)
{ long seektemp;
int i;
MSG_HEADER nf;
char temp[MAX_STR],temp2[MAX_STR];
seektemp = ftell(fhdr);
strcpy(nf.szFrom,X_FIXNAME);
strcpy(nf.szTo,mh.szFrom);
strcpy(nf.szSubject,"Notify");
time(&nf.lDate);
strftime(nf.szDate,20,"%d %b %y %X",localtime(&nf.lDate) );
nf.wFlags = MF_PRIVATE|MF_LOCAL;
#if defined(TEST)
nf.wFlags |= MF_SENT;
#endif
delete_unused_flags(&nf);
nf.wFromZone =myzone;
nf.wFromNet =mynet;
nf.wFromNode =mynode;
nf.wFromPoint=mypoint;
nf.wToZone =mh.wFromZone;
nf.wToNet =mh.wFromNet;
nf.wToNode =mh.wFromNode;
nf.wToPoint =mh.wFromPoint;
sprintf(temp,"%s.MSG",netmail);
fmsg = fopen(temp,"a+b");
nf.wSize = 0;
nf.lStart = ftell(fmsg);
mergeaddr(temp,myzone,mynet,mynode,mypoint,"");
sprintf(temp2,"\001MSGID: %s %04x%04x\n",temp,(int) Random(), (int) Random());
fprintf(fmsg,temp2);
nf.wSize += (int) strlen(temp2);
sprintf(temp2,X_PID);
fprintf(fmsg,temp2);
nf.wSize += (int) strlen(temp2);
sprintf(temp2,"I have received and processed your mail!\n\n");
fprintf(fmsg,temp2);
nf.wSize += (int) strlen(temp2);
for (i=1; i<=err_cnt; i++)
{ fputs(errstack[i].line,fmsg); putc('\n',fmsg);
nf.wSize += (int) strlen(errstack[i].line) +1;
}
sprintf(temp2,X_TEARLINE);
fprintf(fmsg,temp2);
nf.wSize += (int) strlen(temp2);
fclose(fmsg);
fseek(fhdr,0,SEEK_END);
fwrite(&nf,sizeof(MSG_HEADER),1,fhdr);
fseek(fhdr,seektemp,SEEK_SET);
log_it("Write notify");
}
void delete_unused_flags(MSG_HEADER *header)
{ int i;
header->wUp =
header->wReply =
header->wReadcount =
header->wCost = 0;
for (i=0; i<=3; i++)
*(long *)(&header->lMsgidcrc+i) = 0;
}
void convert(char *buffer, int *length)
{ int k,j;
char *src,*dst;
for (k=0; k<=(*length)-1; k++)
{ if (buffer[k]==1)
{ for (j=k+1; j<=(*length)-1; j++)
{ if (buffer[j]==10 || buffer[j]==0)
{ src=&buffer[k];
dst=&buffer[j]+1;
while (dst<=(&buffer[0]+ *length)) *src++=*dst++;
*length -= (int) (&buffer[j]-&buffer[k]+1);
k=-1;
break;
}
}
}
}
}
void getpfad(char *fname, char *xpfad)
{ register char *pointer;
pointer = strrchr(fname,'\\');
if (pointer==NULL)
*xpfad=EOS;
else
{ *pointer=EOS;
strcpy(xpfad,fname);
strcat(xpfad,"\\");
*pointer='\\';
}
}
char *trimstr(char *str)
{ register char *pointer;
char *old=str;
while (isspace(*str) && (*str!=EOS)) str++;
pointer = strchr(str,EOS);
while (isspace(*(--pointer))!=0 && pointer>str) *pointer = EOS;
return(strcpy(old,str));
}
void trim(char **dest)
{ register char *pointer;
while (isspace(**dest)!=0 && *((*dest)++)!=EOS);
pointer = strchr(*dest,EOS);
while (isspace(*(--pointer))!=0 && pointer>*dest) *pointer = EOS;
}
void scanaddr(char *addr,int *zone,int *net,int *node,int *point,char *domain)
{ char *p,*q=NULL,*q1,*q2;
int chr;
q1 = strchr(addr,'\n');
q2 = strchr(addr,'\r');
if (q1!=NULL && q2!=NULL)
q=MIN(q1,q2);
else if (q1!=NULL)
q=q1;
else if (q2!=NULL)
q=q2;
if (q!=NULL)
{ chr=*q;
*q=EOS;
}
p = strchr(addr, ':');
if (p) *zone = atoi(addr);
else *zone = 0;
p = strchr(addr, '/');
if (p) { p--;
while (strchr("0123456789", *p) && (p >= addr)) p--;
p++;
*net = atoi(p);
}
else *net = 0;
p = strchr(addr, '/');
if (p) { p++;
*node = atoi(p);
}
else *node = atoi(addr);
p = strchr(addr, '.');
if (p) { p++;
*point = atoi(p);
}
else *point = 0;
p = strchr(addr, '@');
if (p) { p++;
sscanf(p,"%s",domain);
}
else *domain = EOS;
if (q!=NULL)
*q=chr;
}
char *mergeaddr(char *addr,int zone,int net,int node,int point,char *domain)
{ static char tmp[64];
*addr = EOS;
if (zone) { itoa(zone, tmp, 10);
strcat(addr, tmp);
strcat(addr, ":");
}
if (zone || net) { itoa(net, tmp, 10);
strcat(addr, tmp);
strcat(addr, "/");
}
itoa(node, tmp, 10);
strcat(addr, tmp);
if (point && node) { strcat(addr, ".");
itoa(point, tmp, 10);
strcat(addr, tmp);
}
if (*domain) { strcat(addr, "@");
strcat(addr, domain);
}
return(addr);
}
void input(char *string, int max, FILE *ftype)
{ char temp[512];
long len;
if (fgets(temp, max, ftype)!=NULL)
{ len = (int) strlen(temp);
if (len>0)
if (temp[len-1]=='\n')
temp[len-1] = EOS;
strcpy(string,temp);
}
else
{ *string = EOS;
}
}
void log_it(char *text)
{ char temp[MAX_STR];
FILE *fp;
time_t tim;
if (*logfile!=EOS)
{ if ((fp=fopen(logfile,"a"))!=NULL)
{ tim=time(NULL);
strftime(temp,16,"%d %b %X",localtime(&tim));
fprintf(fp,"* %s DOOR %s\n",temp,text);
fclose(fp);
}
}
}
int xFsfirst(const char *filename,int attr)
{ Fsetdta(&dta_buffer);
return (Fsfirst(filename,attr));
}
int xFsnext(void)
{ return (Fsnext());
}
char *addr2file36(unsigned int net,unsigned int node,unsigned int point)
{ static char filename[13];
char dum[10],*pointer;
itoa(net ,dum,36); sprintf(filename ,"%3s",dum);
itoa(node ,dum,36); sprintf(filename+3,"%3s",dum);
itoa(point,dum,36); sprintf(filename+6,"%2s",dum);
pointer=filename;
while (*pointer!=EOS)
{ if (*pointer==' ')
*pointer = '0';
pointer++;
}
return(filename);
}
void add_slash(char *path)
{ if ( *path!=EOS )
if ( *(path+strlen(path)-1)!='\\' )
strcat(path,"\\");
}